import {ElMessage} from "element-plus";
import router from "../router/index.js";
import {STATUS} from "../const/index.js";
import {elConfirm} from "./element.js";
import {hasNull, isNotNull} from "./index.js";

/**
 * 获取服务器响应中的data数据
 *
 * @param res axios响应结果对象
 * @return result 请求成功时返回data数据或true，响应失败时返回null
 * */
export function getResponseData(res) {

    // 若存在2层data，则直接拆除第1层data
    res = res.data.data !== undefined ? res.data : res;

    // 请求成功：存在data数据就返回data数据，不存在data数据就返回true
    if (res.code === STATUS.SUCCESS) {
        return isNotNull(res.data) ? res.data : true;
    }

    // Token过期：提示并跳转到登录页面
    if (res.code === STATUS.TOKEN_FAILED) {
        ElMessage.warning('Token过期，请重新登录！');
        setTimeout(() => router.push('/'), 1000);
        return null;
    }

    // 请求失败：提示并返回false
    ElMessage.warning('请求失败：' + res.data);
    return null;
}

/**
 * 分页查询数据（异步）
 *
 * <p> api: API请求函数名（不带小括号），必传。
 * <p> params: API请求函数参数，JSON格式，作为请求参数，必传。
 * <p> args: API请求函数参数，JSON格式，不作为请求参数，而是有一些其它作用，可选。
 * <p> records: 分页结果中的数据列表，必传。
 * <p> pageInfo: 分页结果中的分页信息，包括 currentPage，pageSize 和 total 三项，必传。
 */
export async function myPage(config) {

    // 必传参数
    const api = config['api'];
    const records = config['records'];
    const pageInfo = config['pageInfo'];
    const params = config['params'];

    // 空值保护
    if (hasNull(api, params, records, pageInfo)) return;

    // 可选参数
    const args = config['args'];

    // 发送请求
    let res = isNotNull(args) ? await api(params, args) : await api(params);
    let data = getResponseData(res);
    if (isNotNull(data)) {
        records.value = data['list'] || data['records'];
        pageInfo['currentPage'] = data['pageNum'] || data['pageNumber'];
        pageInfo['pageSize'] = data['pageSize'];
        pageInfo['total'] = data['total'] || data['totalRow'];
    }
}

/**
 * 新增一条数据（表单，异步）
 *
 * <p> form: 表单对象，必须是reactive变量，必传。
 * <p> api: API请求函数名（不带小括号），必传。
 * <p> params: API请求函数参数，JSON格式，作为请求参数，必传。
 * <p> args: API请求函数参数，JSON格式，不作为请求参数，而是有一些其它作用，可选。
 * <p> callback: 回调函数名（不带小括号），即当操作成功后调用的函数，可选。
 * <p> successTip: 是否需要成功提示，默认true，可选。
 * <p> successTipContent: 操作成功后的提示文字，可选。
 * */
export async function myInsert(config) {

    // 必传参数
    const form = config['form'];
    const api = config['api'];
    const params = config['params'];

    // 空值保护
    if (hasNull(form, api, params)) return;

    // 可选参数
    const args = config['args'];
    const callback = config['callback'];
    const successTip = isNotNull(config['successTip']) ?
        config['successTip'] : true;
    const successTipContent = isNotNull(config['successTipContent']) ?
        config['successTipContent'] : '操作成功！';

    // 验证表单：只有全部校验规则都通过，valid参数才为true。
    form.value.validate(async (valid) => {
        if (valid) {
            // 发送请求
            let res = isNotNull(args) ? await api(params, args) : await api(params);
            let data = getResponseData(res);
            if (isNotNull(data)) {
                // 开启成功提示时，进行成功提示
                if (successTip) ElMessage.success(successTipContent);
                // 存在回调函数时，异步调用回调函数
                if (callback) await callback();
            }
        }
    });
}

/**
 * 修改一条数据（表单，异步）
 *
 * <p> form: 表单对象，必须是reactive变量，必传。
 * <p> api: API请求函数名（不带小括号），必传。
 * <p> params: API请求函数参数，JSON格式，作为请求参数，必传。
 * <p> args: API请求函数参数，JSON格式，不作为请求参数，而是有一些其它作用，可选。
 * <p> callback: 回调函数名（不带小括号），即当操作成功后调用的函数，可选。
 * <p> successTip: 是否需要成功提示，默认true，可选。
 * <p> successTipContent: 操作成功后的提示文字，可选。
 */
export async function myUpdate(config) {
    await myInsert(config);
}

/**
 * 删除一条数据（异步）
 *
 * <p> id: 数据主键，必传。
 * <p> api: API请求函数名（不带小括号），必传。
 * <p> args: API请求函数参数，JSON格式，不作为请求参数，而是有一些其它作用，可选。
 * <p> callback: 回调函数名（不带小括号），即当操作成功后调用的函数，可选。
 * <p> successTip: 是否需要成功提示，默认true，可选。
 * <p> successTipContent: 操作成功后的提示文字，可选。
 * <p> confirmTip: 是否需要危险操作保护提示，默认true，可选。
 * <p> confirmTipContent: 危险操作保护提示文字，可选。
 */
export async function myDelete(config) {

    // 必传参数
    const id = config['id'];
    const api = config['api'];

    // 空值保护
    if (hasNull(id, api)) return;

    // 可选参数
    const args = config['args'];
    const callback = config['callback'];
    const successTip = isNotNull(config['successTip']) ? config['successTip'] : true;
    const successTipContent = isNotNull(config['successTipContent']) ?
        config['successTipContent'] : '操作成功！';
    const confirmTip = isNotNull(config['confirmTip']) ? config['confirmTip'] : true;
    const confirmTipContent = isNotNull(config['confirmTipContent']) ?
        config['confirmTipContent'] : '即将删除1条数据，确认吗？';

    // 危险操作保护
    if (confirmTip) {
        if (!await elConfirm(confirmTipContent)) return;
    }

    // 发送请求
    let res = isNotNull(args) ? await api(id, args) : await api(id);
    let data = getResponseData(res);
    if (isNotNull(data)) {
        // 开启成功提示时，进行成功提示
        if (successTip) ElMessage.success(successTipContent);
        // 存在回调函数时，异步调用回调函数
        if (callback) await callback();
    }
}

/**
 * 批量删除数据（异步）
 *
 * <p> ids: 主键数组，必传。
 * <p> api: API请求函数名（不带小括号），必传。
 * <p> args: API请求函数参数，JSON格式，不作为请求参数，而是有一些其它作用，可选。
 * <p> callback: 回调函数名（不带小括号），即当操作成功后调用的函数，可选。
 * <p> successTip: 是否需要成功提示，默认true，可选。
 * <p> successTipContent: 操作成功后的提示文字，可选。
 * <p> confirmTip: 是否需要危险操作保护提示，默认true，可选。
 * <p> confirmTipContent: 危险操作保护提示文字，可选。
 */
export async function myDeleteBatch(config) {

    // 必传参数
    const ids = config['ids'];
    const api = config['api'];

    // 空值保护
    if (hasNull(ids, api)) return;

    // 主键数组保护
    if (ids.length <= 0) {
        ElMessage.warning('至少选择1项！');
        return;
    }

    // 可选参数
    const args = config['args'];
    const callback = config['callback'];
    const successTip = isNotNull(config['successTip']) ? config['successTip'] : true;
    const successTipContent = isNotNull(config['successTipContent']) ?
        config['successTipContent'] : '操作成功！';
    const confirmTip = isNotNull(config['confirmTip']) ? config['confirmTip'] : true;
    const confirmTipContent = isNotNull(config['confirmTipContent']) ?
        config['confirmTipContent'] : `即将删除 ${ids.length} 条数据，确认吗？`;

    // 危险操作保护
    if (confirmTip) {
        if (!await elConfirm(confirmTipContent)) return;
    }

    // 发送请求
    let res = isNotNull(args) ? await api(ids.join(','), args) : await api(ids.join(','));
    let data = getResponseData(res);
    if (isNotNull(data)) {
        // 开启成功提示时，进行成功提示
        if (successTip) ElMessage.success(successTipContent);
        // 存在回调函数时，异步调用回调函数
        if (callback) await callback();
    }
}